package com.szly.phm.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.*;

/**
 * token工具类
 *
 * @author chengjiang
 * @date
 */
public class TokenUtils {
    // 过期时间2小时
    private static final long EXPIRE_TIME = 1000 * 60*150;
    // token主题前缀
    private static String SUBJECT_PREFIX = "phm后台管理";

    //私钥
    private static String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK4MzcNElmi/6CX+\n" +
            "4SDQ8oygQB579GBiyXGsKk5nWB138OyNQe3Tc1mIWGYsbH7Otle7AFCXI8xozbsO\n" +
            "S+FDak3AL5t1beJ1JzFNuVQ9ijP6H8LVfcIqJ3a2bLqTJso/ohMf3vKdMp11MmO2\n" +
            "wvzRlEHKHJ5G7cfeJ6j8o4z1PMOpAgMBAAECgYBqouuafLZOnW2FggC602oX4MMI\n" +
            "KlfSihPz8lDFUqn4/Bh/Rhijts7QhynqB8O9ebbcT3Vk6wUC4x9RQPQaouxIjhPl\n" +
            "3ePWbNVvZrdVm/0YNr8amqnByqI4GC5jgzFCd8TDM8FxY4XQ++mFwaxGwvq0klpt\n" +
            "lFedgBCoChvvoUHYJQJBANOG5s/PG6YgzyubwGd1A26FDOamMY8SRssXt0L/54P9\n" +
            "bq4/LWOSrI2s/gh8zeSk4fpX0ndh4nZv19+f9MHq4nMCQQDSpMQQhaKzBi2FTxuI\n" +
            "YpNWIuxlG3zdSXzyZklTjTKCxw7gAeJA5EPnYkuQo90hk1UYBGZRnTaZwlyHxhp4\n" +
            "3k5zAkBeTcxlZW5sOEBkrsGu3iozgbnosrtxj7JkJSSdCD4NSFWp9ZykweWQHEn9\n" +
            "OrcIcsIUvEam1ssCBob1ufiC49clAkBHSgQhI1khBaI6T7+dtN7wc/lVbqwfqFNl\n" +
            "JkECyfKiWAQsw/Zyx85DbPzuAsdAKcDO1A5c6Lwl5aWzPdSPu40JAkBiZv9Q4cHI\n" +
            "V/gO7WQQl/eSBzlhVGHG/uYl2liwNcD/u9LkjHBrHylwLTPMWUyZgxlTa44FCoL9\n" +
            "Y0rvXU/Kmd1a";
    //公钥
    private static String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuDM3DRJZov+gl/uEg0PKMoEAe\n" +
            "e/RgYslxrCpOZ1gdd/DsjUHt03NZiFhmLGx+zrZXuwBQlyPMaM27DkvhQ2pNwC+b\n" +
            "dW3idScxTblUPYoz+h/C1X3CKid2tmy6kybKP6ITH97ynTKddTJjtsL80ZRByhye\n" +
            "Ru3H3ieo/KOM9TzDqQIDAQAB";

    public static String signKey = "2022/2023-CDU/PHM|author:chengjiang@stu.cdu.edu.cn";
    /**
     * 创建令牌token(无过期时间)
     */
    public static String createToken(String userId) {
        // alg属性表示签名的算法（algorithm），默认是HMAC SHA256（写成HS256）；typ属性表示这个令牌（token）的类型（type），JWT令牌统一写为JWT。
        var map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        var token = JWT.create()
                // 添加头部
                .withHeader(map)
                // 添加用户Id
                .withAudience(userId)
                // 主题
//                .withSubject(SUBJECT_PREFIX)
                // 可以放些基本信息比如：用户名、设备号等等
//                .withClaim("realName",realName)
//                .withClaim("userName",userName)
                // 签发时间
//                .withIssuedAt(new Date())
                // 加密
                .sign(Algorithm.HMAC256(signKey));
        return token;
    }

    /**
     * 创建令牌token(有过期时间)
     */
    public static String createTokenExpire(String userId, String secretKey) {
        // alg属性表示签名的算法（algorithm），默认是HMAC SHA256（写成HS256）；typ属性表示这个令牌（token）的类型（type），JWT令牌统一写为JWT。
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        var map = new HashMap<String, Object>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        var prk = RSAKeyUtils.toPrikey(privateKey);
        var puk = RSAKeyUtils.toPubkey(publicKey);
        var token = JWT.create()
                // 添加头部
                .withHeader(map)
                // 添加用户Id
                .withAudience(userId)
                // 主题
//                .withSubject(SUBJECT_PREFIX)
//                 设置过期时间
                .withExpiresAt(date)
                // 签发时间
//                .withIssuedAt(new Date(System.currentTimeMillis()))
                // 加密
                .sign(Algorithm.HMAC256(signKey));
        return token;
    }

    /**
     * 解析token，获取用户Id
     */
    public static String parseToken(String token, String secretKey) {
        try {
            var verifier = JWT.require(Algorithm.HMAC256(signKey)).build();
            var jwt = verifier.verify(token);
            if (jwt != null) {
                // 拿到我们放置在token中的信息
                var audience = jwt.getAudience();
                if (audience != null && !audience.isEmpty()) {
                    return audience.get(0);
                }
            }
        } catch (Exception e) {
            e.getStackTrace();
            return null;
        }
        return null;
    }

    /**
     * 解析token，获取用户Id和角色Id
     */
    public static HashMap parseTokenUserIdAndRoleId(String token) {
        var map = new HashMap<String, String>();
        try {
            var verifier = JWT.require(Algorithm.RSA256(RSAKeyUtils.toPubkey(publicKey))).build();
            var jwt = verifier.verify(token);
            if (jwt != null) {
                // 获取token中的用户Id
                var audience = jwt.getAudience();
                if (audience != null && !audience.isEmpty()) {
                    map.put("userId", audience.get(0));
                }
                // 获取token中的角色Id
                var claim = jwt.getClaim("roleId");
                if (claim != null) {
                    var roleId = claim.asString();
                    map.put("roleId", roleId);
                }
            }
            return map;
        } catch (Exception e) {
            e.getStackTrace();
            return map;
        }
    }

    /**
     * 刷新 token的过期时间
     */
    public static String refreshTokenExpired(String token, String secret) {
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Claim> claims = jwt.getClaims();
        try {
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTCreator.Builder builer = JWT.create().withExpiresAt(date);
            for (Map.Entry<String, Claim> entry : claims.entrySet()) {
                builer.withClaim(entry.getKey(), entry.getValue().asString());
            }
            return builer.sign(algorithm);
        } catch (JWTCreationException e) {
            return null;
        }
    }

    /**
     * @ Description   :  验证token
     * @ Author        :  chengjiang
     * @ Date          :  2021/7/19
     */
    public static String verify(String userId,String token, String secretKey) {
        JWT.require(Algorithm.HMAC256(signKey)).build().verify(token);
        DecodedJWT jwt = JWT.decode(token);
        Map<String, Claim> claims = jwt.getClaims();
        Claim exp = claims.get("exp");
        Date date = exp.asDate();
        if(date.getTime()-new Date().getTime()<1000*60*30){
            return createTokenExpire(userId,"secretKey");
        }else {
            return "";
        }
    }
}
